import type { Settings as LayoutSettings } from '@ant-design/pro-layout';
import { PageLoading } from '@ant-design/pro-layout';
import type { RequestConfig, RunTimeLayoutConfig } from 'umi';
import { Access, useAccess } from 'umi';
import RightContent from '@/components/RightContent';
import defaultSettings from '../config/defaultSettings';
import Keycloak from 'keycloak-js';
import { ReactKeycloakProvider } from '@react-keycloak/web';
import { API_PERFIX, CURRENT_GROUP_KEY } from './constants';
import React from 'react';
import { getUser } from './pages/User/api';
import { Button, Modal, Result } from 'antd';

const keycloak = Keycloak(window.appConfig.keycloakConfig);

/** 获取用户信息比较慢的时候会展示一个 loading */
export const initialStateConfig = {
  loading: <PageLoading />,
};

/**
 * @see  https://umijs.org/zh-CN/plugins/plugin-initial-state
 * */
export async function getInitialState(): Promise<{
  settings?: Partial<LayoutSettings>;
  currentUser?: CurrentUser;
  loading?: boolean;
}> {
  return {
    settings: defaultSettings,
  };
}

// ProLayout 支持的api https://procomponents.ant.design/components/layout
export const layout: RunTimeLayoutConfig = ({ initialState, setInitialState, loading }) => {
  if (!initialState?.currentUser) {
    const handleError = () => {
      Modal.error({
        title: '错误',
        content: '获取当前用户信息出错，请检查服务是否正常！',
        onOk: () => keycloak.logout(),
      });
    };

    keycloak
      .loadUserInfo()
      .then((res) => {
        if (res) {
          const kcInfo = res as KeycloakUser;
          getUser(kcInfo.sub)
            .then((user) => {
              const { groups = [] } = user;
              let newCurrentGroup = '';
              let newCurrentGroupName = '';
              if (groups.length > 0) {
                const currentGroup = localStorage.getItem(CURRENT_GROUP_KEY);
                const newGroup = groups.find((item) => item.tenant_id === currentGroup);
                if (newGroup) {
                  newCurrentGroup = newGroup.tenant_id;
                  newCurrentGroupName = newGroup.tenant_name;
                } else {
                  newCurrentGroup = groups[0].tenant_id;
                  newCurrentGroupName = groups[0].tenant_name;
                  localStorage.setItem(CURRENT_GROUP_KEY, newCurrentGroup);
                }
              }
              setInitialState({
                ...initialState,
                currentUser: {
                  id: kcInfo.sub,
                  username: user.username,
                  name: kcInfo.name,
                  firstName: user.first_name,
                  lastName: user.last_name,
                  email: user.email,
                  groups: user.groups,
                  currentGroup: newCurrentGroup,
                  currentGroupName: newCurrentGroupName,
                  isAdmin: user.is_admin,
                },
              });
            })
            .catch(() => handleError());
        }
      })
      .catch(() => handleError());
  }
  return {
    loading: !initialState?.currentUser || loading,
    rightContentRender: () => <RightContent />,
    disableContentMargin: true,
    onPageChange: () => {
      if (!keycloak.authenticated) {
        keycloak.logout();
      }
    },
    menuHeaderRender: undefined,
    childrenRender: (children) => {
      // eslint-disable-next-line react-hooks/rules-of-hooks
      const access = useAccess();
      return (
        <Access
          accessible={access.hasGroup}
          fallback={
            <Result
              status="403"
              title="抱歉，您未分配角色，请联系管理员。"
              extra={
                <Button type="primary" onClick={() => keycloak.logout()}>
                  确定
                </Button>
              }
            />
          }
        >
          <div className="basic-full-page">{children}</div>
        </Access>
      );
    },
    ...initialState?.settings,
  };
};

/**
 * rootContainer 与 route access 有冲突, 必须通过这种Wrapper才起效
 * https://github.com/umijs/umi/issues/5747
 */
const Wrapper = ({ children, routes }: any) => (
  <ReactKeycloakProvider
    authClient={keycloak}
    initOptions={{
      onLoad: 'login-required',
      checkLoginIframe: false,
      enableLogging: false,
    }}
    isLoadingCheck={(authClient) => !authClient.authenticated}
    LoadingComponent={<PageLoading />}
    onEvent={(event) => {
      if (event === 'onTokenExpired') {
        keycloak.logout();
        return;
      }
      if (event === 'onAuthSuccess') {
        return;
      }
    }}
  >
    {React.cloneElement(children, {
      ...children.props,
      routes,
    })}
  </ReactKeycloakProvider>
);

export function rootContainer(container: React.ReactNode) {
  return React.createElement(Wrapper, null, container);
}

export const request: RequestConfig = {
  timeout: 10000,
  credentials: 'include',
  errorConfig: {},
  requestInterceptors: [
    (url, options) => {
      const { headers = {} } = options;

      return {
        url: `${API_PERFIX}${url}`,
        options: {
          ...options,
          headers: {
            token: keycloak.token || '',
            group: localStorage.getItem(CURRENT_GROUP_KEY) || '',
            ...headers,
          },
          interceptors: true,
        },
      };
    },
  ],
  responseInterceptors: [],
  errorHandler: (error) => {
    throw error;
  },
};
